import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from scipy import interpolate

# 设置Matplotlib的字体参数
plt.rcParams['font.family'] = 'SimHei' # 选择一个支持中文的字体
plt.rcParams['axes.unicode_minus'] = False # 正确显示负号

FILE_PATH='./data/cache_resultsKJI.csv'

def analyze_all_matrices_cache_behavior():
    """分析A、B、C三个矩阵的缓存行为"""
    
    # 读取数据
    df = pd.read_csv(FILE_PATH)
    # 删除所有 hits=0 的行
    if 'hits' in df.columns:
        df = df[df['hits'] != 0].reset_index(drop=True)
    df=df.drop_duplicates().reset_index(drop=True)
    
    # 分离三个矩阵的数据
    df_a = df[df['matrix_type'] == 'A'].copy().sort_values('cache_size')
    df_b = df[df['matrix_type'] == 'B'].copy().sort_values('cache_size')
    df_c = df[df['matrix_type'] == 'C'].copy().sort_values('cache_size')
    
    # 创建综合图表
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    fig.suptitle('A、B、C三个矩阵的缓存行为对比分析\n(矩阵大小: 124*124, 缓存行: 32字节)', 
                 fontsize=16, fontweight='bold')
    
    # 颜色定义
    colors = {'A': 'blue', 'B': 'red', 'C': 'green'}
    
    # 子图1: 三个矩阵的缺失次数对比
    ax1 = axes[0, 0]
    
    # 绘制三个矩阵的缺失曲线
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax1.plot(df_matrix['cache_size'], df_matrix['misses'], 
                'o-', color=color, label=f'矩阵{matrix_type}', alpha=0.7, markersize=4)
    
    ax1.set_xlabel('缓存大小 (字节)')
    ax1.set_ylabel('缺失次数')
    ax1.set_title('三个矩阵的缺失次数对比')
    ax1.legend()
    ax1.grid(True, alpha=0.3)
    ax1.set_xscale('log')
    ax1.set_yscale('log')
    
    # 子图2: 三个矩阵的命中率对比
    ax2 = axes[0, 1]
    
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax2.plot(df_matrix['cache_size'], df_matrix['hit_rate'], 
                'o-', color=color, label=f'矩阵{matrix_type}', alpha=0.7, markersize=4)
    
    ax2.set_xlabel('缓存大小 (字节)')
    ax2.set_ylabel('命中率')
    ax2.set_title('三个矩阵的命中率对比')
    ax2.legend()
    ax2.grid(True, alpha=0.3)
    ax2.set_xscale('log')
    
    # 子图3: 三个矩阵的空间局部性对比
    ax3 = axes[1, 0]
    
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax3.plot(df_matrix['cache_size'], df_matrix['spatial_locality'], 
                'o-', color=color, label=f'矩阵{matrix_type}', alpha=0.7, markersize=4)
    
    ax3.set_xlabel('缓存大小 (字节)')
    ax3.set_ylabel('空间局部性')
    ax3.set_title('三个矩阵的空间局部性对比')
    ax3.legend()
    ax3.grid(True, alpha=0.3)
    ax3.set_xscale('log')
    
    # 子图4: 缺失次数减少百分比
    ax4 = axes[1, 1]
    
    # 计算每个矩阵从最小缓存到最大缓存的缺失减少百分比
    reduction_data = []
    for matrix_type in ['A', 'B', 'C']:
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        min_cache_misses = df_matrix['misses'].iloc[0]
        max_cache_misses = df_matrix['misses'].iloc[-1]
        reduction = (min_cache_misses - max_cache_misses) / min_cache_misses * 100
        
        reduction_data.append({
            'matrix': matrix_type,
            'reduction_percent': reduction,
            'min_misses': min_cache_misses,
            'max_misses': max_cache_misses
        })
    
    reduction_df = pd.DataFrame(reduction_data)
    bars = ax4.bar(reduction_df['matrix'], reduction_df['reduction_percent'], 
                   color=[colors[m] for m in reduction_df['matrix']], alpha=0.7)
    
    # 在柱子上添加数值标签
    for bar, reduction in zip(bars, reduction_df['reduction_percent']):
        height = bar.get_height()
        ax4.text(bar.get_x() + bar.get_width()/2., height,
                f'{reduction:.1f}%', ha='center', va='bottom', fontsize=12)
    
    ax4.set_xlabel('矩阵类型')
    ax4.set_ylabel('缺失减少百分比 (%)')
    ax4.set_title('从最小缓存到最大缓存的缺失减少百分比')
    ax4.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('all_matrices_cache_behavior.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    # 生成详细对比报告
    generate_comparative_analysis(df_a, df_b, df_c)

def generate_comparative_analysis(df_a, df_b, df_c):
    """生成三个矩阵的对比分析报告"""
    
    print("=" * 80)
    print("A、B、C三个矩阵缓存行为对比分析报告")
    print("=" * 80)
    
    # 基本统计信息
    n = df_a['matrix_size'].iloc[0]
    block_size = df_a['block_size'].iloc[0]
    
    print(f"\n1. 实验参数:")
    print(f"   矩阵大小: {n} × {n}")
    print(f"   缓存行大小: {block_size} 字节")
    print(f"   测试缓存大小范围: {df_a['cache_size'].min():,} - {df_a['cache_size'].max():,} 字节")
    
    # 各矩阵的关键统计数据
    matrices_data = {
        'A': df_a,
        'B': df_b, 
        'C': df_c
    }
    
    print(f"\n2. 各矩阵缓存行为总结:")
    for matrix_type, df_matrix in matrices_data.items():
        min_cache_misses = df_matrix['misses'].min()
        max_cache_misses = df_matrix['misses'].max()
        min_cache_size = df_matrix[df_matrix['misses'] == min_cache_misses]['cache_size'].iloc[0]
        max_cache_size = df_matrix[df_matrix['misses'] == max_cache_misses]['cache_size'].iloc[0]
        
        reduction = (max_cache_misses - min_cache_misses) / max_cache_misses * 100
        
        print(f"\n   矩阵{matrix_type}:")
        print(f"     最小缺失数: {min_cache_misses:,} (缓存大小: {min_cache_size:,} 字节)")
        print(f"     最大缺失数: {max_cache_misses:,} (缓存大小: {max_cache_size:,} 字节)")
        print(f"     缺失减少百分比: {reduction:.1f}%")
        print(f"     最佳命中率: {df_matrix['hit_rate'].max():.4f}")
        print(f"     平均空间局部性: {df_matrix['spatial_locality'].mean():.4f}")
    
    # 理论分析
    print(f"\n3. 理论分析:")
    w = block_size // 4  # 每个元素4字节
    
    # 矩阵A和C的理论值 (行优先访问)
    theoretical_a_c_small = n * (n / w)  # n²/w
    theoretical_a_c_large = n * (n / w)  # 不变
    
    # 矩阵B的理论值
    theoretical_b_small = n * n * (n / w)  # n³/w
    theoretical_b_large = n * (n / w)      # n²/w
    
    print(f"   矩阵A和C理论缺失 (n²/w): {theoretical_a_c_small:,.0f}")
    print(f"   矩阵B理论小缓存缺失 (n³/w): {theoretical_b_small:,.0f}")
    print(f"   矩阵B理论大缓存缺失 (n²/w): {theoretical_b_large:,.0f}")
    
    # 访问模式分析
    print(f"\n4. 访问模式分析:")
    print(f"   矩阵A (A[i][k]): 行优先访问，空间局部性极好")
    print(f"   矩阵B (B[k][j]): 缓存敏感，小缓存时类似列访问，大缓存时行访问")
    print(f"   矩阵C (C[i][j]): 重复写入，时间局部性好")
    
    # 缓存容量临界点分析
    print(f"\n5. 缓存容量临界点分析:")
    
    # 找到B矩阵的临界点
    b_misses = df_b['misses'].values
    b_cache_sizes = df_b['cache_size'].values
    
    # 使用变化率找到临界点
    miss_reductions = np.diff(b_misses) / np.diff(b_cache_sizes)
    critical_idx = np.argmax(np.abs(miss_reductions)) + 1
    
    if critical_idx < len(b_cache_sizes):
        critical_cache_size = b_cache_sizes[critical_idx]
        print(f"   矩阵B的缓存临界点: {critical_cache_size:,} 字节")
        
        # 计算临界点对应的缓存容量（以矩阵行数计）
        elements_per_row = n
        bytes_per_row = elements_per_row * 4
        rows_in_cache = critical_cache_size // bytes_per_row
        
        print(f"   临界缓存可容纳约 {rows_in_cache} 行矩阵数据")
        print(f"   这大约是矩阵总行数({n})的 {rows_in_cache/n*100:.1f}%")
    
    # 性能影响评估
    print(f"\n6. 性能影响评估:")
    
    # 假设内存访问时间
    memory_access_time = 100  # ns
    cache_access_time = 1     # ns
    
    total_accesses = 3 * n * n * n  # 三个矩阵的总访问次数
    
    for matrix_type, df_matrix in matrices_data.items():
        min_misses = df_matrix['misses'].min()
        max_misses = df_matrix['misses'].max()
        
        time_min_cache = (max_misses * memory_access_time + 
                         (total_accesses/3 - max_misses) * cache_access_time)
        time_max_cache = (min_misses * memory_access_time + 
                         (total_accesses/3 - min_misses) * cache_access_time)
        
        speedup = time_min_cache / time_max_cache if time_max_cache > 0 else 1
        
        print(f"   矩阵{matrix_type}性能提升: {speedup:.2f} 倍")
    
    # 设计建议
    print(f"\n7. 缓存设计建议:")
    print(f"   ✅ 对于IJK顺序")
    print(f"   ✅ 确保缓存足够大以容纳B矩阵的多行数据")
    print(f"   ✅ 矩阵A和C对缓存容量不敏感，但受益于大缓存行")
    print(f"   ✅ 推荐缓存大小: >60KB 以获得最佳性能")

def plot_detailed_comparison():
    """绘制更详细的三个矩阵对比图"""
    
    df = pd.read_csv(FILE_PATH)
    
    # 创建更详细的分析图表
    fig, axes = plt.subplots(2, 3, figsize=(18, 12))
    
    colors = {'A': 'blue', 'B': 'red', 'C': 'green'}
    markers = {'A': 'o', 'B': 's', 'C': '^'}
    
    # 提取所有唯一的缓存大小
    cache_sizes = sorted(df['cache_size'].unique())
    
    # 子图1: 缺失次数（线性尺度）
    ax1 = axes[0, 0]
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax1.plot(df_matrix['cache_size'], df_matrix['misses'], 
                marker=markers[matrix_type], color=color, 
                label=f'矩阵{matrix_type}', alpha=0.7, markersize=5)
    
    ax1.set_xlabel('缓存大小 (字节)')
    ax1.set_ylabel('缺失次数')
    ax1.set_title('缺失次数 vs 缓存大小 (线性尺度)')
    ax1.legend()
    ax1.grid(True, alpha=0.3)
    
    # 子图2: 缺失次数（对数尺度）
    ax2 = axes[0, 1]
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax2.semilogy(df_matrix['cache_size'], df_matrix['misses'], 
                    marker=markers[matrix_type], color=color, 
                    label=f'矩阵{matrix_type}', alpha=0.7, markersize=5)
    
    ax2.set_xlabel('缓存大小 (字节)')
    ax2.set_ylabel('缺失次数 (对数尺度)')
    ax2.set_title('缺失次数 vs 缓存大小 (对数尺度)')
    ax2.legend()
    ax2.grid(True, alpha=0.3)
    
    # 子图3: 命中率
    ax3 = axes[0, 2]
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax3.plot(df_matrix['cache_size'], df_matrix['hit_rate']*100, 
                marker=markers[matrix_type], color=color, 
                label=f'矩阵{matrix_type}', alpha=0.7, markersize=5)
    
    ax3.set_xlabel('缓存大小 (字节)')
    ax3.set_ylabel('命中率 (%)')
    ax3.set_title('命中率 vs 缓存大小')
    ax3.legend()
    ax3.grid(True, alpha=0.3)
    
    # 子图4: 空间局部性
    ax4 = axes[1, 0]
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax4.plot(df_matrix['cache_size'], df_matrix['spatial_locality']*100, 
                marker=markers[matrix_type], color=color, 
                label=f'矩阵{matrix_type}', alpha=0.7, markersize=5)
    
    ax4.set_xlabel('缓存大小 (字节)')
    ax4.set_ylabel('空间局部性 (%)')
    ax4.set_title('空间局部性 vs 缓存大小')
    ax4.legend()
    ax4.grid(True, alpha=0.3)
    
    # 子图5: 缺失率对比
    ax5 = axes[1, 1]
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax5.plot(df_matrix['cache_size'], df_matrix['miss_rate']*100, 
                marker=markers[matrix_type], color=color, 
                label=f'矩阵{matrix_type}', alpha=0.7, markersize=5)
    
    ax5.set_xlabel('缓存大小 (字节)')
    ax5.set_ylabel('缺失率 (%)')
    ax5.set_title('缺失率 vs 缓存大小')
    ax5.legend()
    ax5.grid(True, alpha=0.3)
    
    # 子图6: 三个矩阵的缺失比率
    ax6 = axes[1, 2]
    
    # 计算每个缓存大小下三个矩阵的缺失比率
    ratio_data = []
    for cache_size in cache_sizes:
        cache_data = df[df['cache_size'] == cache_size]
        if len(cache_data) == 3:  # 确保有A、B、C三个矩阵的数据
            total_misses = cache_data['misses'].sum()
            for _, row in cache_data.iterrows():
                ratio_data.append({
                    'cache_size': cache_size,
                    'matrix_type': row['matrix_type'],
                    'miss_ratio': row['misses'] / total_misses * 100
                })
    
    ratio_df = pd.DataFrame(ratio_data)
    
    for matrix_type, color in colors.items():
        matrix_ratio = ratio_df[ratio_df['matrix_type'] == matrix_type].sort_values('cache_size')
        ax6.plot(matrix_ratio['cache_size'], matrix_ratio['miss_ratio'], 
                marker=markers[matrix_type], color=color, 
                label=f'矩阵{matrix_type}', alpha=0.7, markersize=5)
    
    ax6.set_xlabel('缓存大小 (字节)')
    ax6.set_ylabel('缺失占比 (%)')
    ax6.set_title('各矩阵缺失占总缺失的百分比')
    ax6.legend()
    ax6.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('detailed_matrices_comparison.png', dpi=300, bbox_inches='tight')
    plt.show()

def analyze_miss_vs_matrix_size():
    df = pd.read_csv(FILE_PATH)
    
    # 去掉异常行
    if 'misses' in df.columns:
        df = df[df['misses'] != 0].reset_index(drop=True)
    df = df.drop_duplicates().reset_index(drop=True)

    # 按矩阵类型与矩阵大小分组
    df = df.sort_values(['matrix_type', 'block_size'])
    colors = {'A': 'blue', 'B': 'red', 'C': 'green'}
    markers = {'A': 'o', 'B': 's', 'C': '^'}
    
    # 创建图像
    plt.figure(figsize=(10, 7))
    plt.title("不同缓存区大小下的缓存缺失行为", fontsize=15, fontweight='bold')

    # 绘制每个矩阵的缺失率随矩阵大小变化曲线
    for matrix_type, color in colors.items():
        df_matrix = df[df['matrix_type'] == matrix_type]
        if not df_matrix.empty:
            plt.plot(df_matrix['block_size'], df_matrix['misses'],
                     marker=markers[matrix_type], color=color,
                     label=f'矩阵{matrix_type}', alpha=0.8, markersize=6)
    
    plt.xlabel("缓存区大小")
    plt.ylabel("缺失数量")
    plt.grid(True, alpha=0.3)
    plt.legend()
    plt.tight_layout()
    plt.savefig("miss_vs_matrix_size.png", dpi=300, bbox_inches='tight')
    plt.show()


if __name__ == "__main__":
    analyze_all_matrices_cache_behavior()
    # analyze_miss_vs_matrix_size()
    plot_detailed_comparison()
    
    # 额外生成一个关键观察总结
    print("\n" + "="*80)
    print("关键观察总结")
    print("="*80)
    
    # df = pd.read_csv(FILE_PATH)
    
    # # 计算各矩阵在小缓存和大缓存下的表现差异
    # small_cache = df[df['cache_size'] == df['cache_size'].min()]
    # large_cache = df[df['cache_size'] == df['cache_size'].max()]
    
    # print("\n小缓存 vs 大缓存表现对比:")
    # for matrix_type in ['A', 'B', 'C']:
    #     small_data = small_cache[small_cache['matrix_type'] == matrix_type].iloc[0]
    #     large_data = large_cache[large_cache['matrix_type'] == matrix_type].iloc[0]
        
    #     miss_reduction = (small_data['misses'] - large_data['misses']) / small_data['misses'] * 100
    #     hit_rate_improvement = (large_data['hit_rate'] - small_data['hit_rate']) * 100
        
    #     print(f"\n矩阵{matrix_type}:")
    #     print(f"  缺失次数: {small_data['misses']:,} → {large_data['misses']:,} (减少{miss_reduction:.1f}%)")
    #     print(f"  命中率: {small_data['hit_rate']:.3f} → {large_data['hit_rate']:.3f} (提升{hit_rate_improvement:.2f}%)")
    #     print(f"  空间局部性: {small_data['spatial_locality']:.3f} → {large_data['spatial_locality']:.3f}")

    plot_detailed_comparison()
